/** @file gui_button.cpp
    @brief A button widget */

#include "gui/gui_button.h"

using namespace G3;
using namespace GUI;

//==============================================================================
// Constructors
//==============================================================================
G3::GUI::BUTTON::BUTTON () {
    FgVisible = true;
    BgVisible = true;

    BgColor [WIDGET::W_UP  ] = COL4F (0.6f, 0.6f, 0.6f, 1.0f);
    FgColor [WIDGET::W_UP  ] = COL4F (0.7f, 0.7f, 0.7f, 1.0f);
    BgColor [WIDGET::W_OVER] = COL4F (0.6f, 0.6f, 0.6f, 1.0f);
    FgColor [WIDGET::W_OVER] = COL4F (1.0f, 1.0f, 1.0f, 1.0f);
    BgColor [WIDGET::W_DOWN] = COL4F (0.7f, 0.7f, 0.7f, 1.0f);
    FgColor [WIDGET::W_DOWN] = COL4F (1.0f, 1.0f, 1.0f, 1.0f);
}

//==============================================================================
// Destructors
//==============================================================================

// Just chill?

//==============================================================================
// = operators
//==============================================================================
G3::GUI::BUTTON& G3::GUI::BUTTON::operator= (const BUTTON &aButton) {
    Visible = aButton.Visible;
    Rect = aButton.Rect;
    Children = aButton.Children;

    BgColor [0] = aButton.BgColor [0];
    BgColor [1] = aButton.BgColor [1];
    BgColor [2] = aButton.BgColor [2];
    FgColor [0] = aButton.FgColor [0];
    FgColor [1] = aButton.FgColor [1];
    FgColor [2] = aButton.FgColor [2];
    FgVisible = aButton.FgVisible;
    BgVisible = aButton.BgVisible;

    // NOTE:: Signals are not copyable

    return *this;
}

//==============================================================================
// Creates the button
//==============================================================================
void G3::GUI::BUTTON::Create (const RECTI &aRect, FONT *aFont, const std::string &aCaption) {
    SetRect (aRect);

    if (aFont != NULL) {
        AttachFont (aFont);
        SetCaption (aCaption);
    }
}

//==============================================================================
// Sets button dimensions
//==============================================================================
void G3::GUI::BUTTON::SetRect (const RECTI &aRect) {
    Rect.Left = aRect.Left;
    Rect.Top = aRect.Top;

    if (!Children.empty () && Children [0]) {
        Children [0]->SetPosition (VEC2I (Rect.Left + 5, Rect.Top + 5));

        Rect.Right = G3_MAX (aRect.Right, Children [0]->Rect.Right + 5);
        Rect.Bottom = G3_MAX (aRect.Bottom, Children [0]->Rect.Bottom + 5);
    } else {
        Rect.Right = aRect.Right;
        Rect.Bottom = aRect.Bottom;
    }
}

//==============================================================================
// Attaches a font to the button label
//==============================================================================
void G3::GUI::BUTTON::AttachFont (FONT *aFont) {
    if (Children.empty () || !Children [0]) {
        Children.push_back (new LABEL);

        Assert (Children [0], "BUTTON::AttachFont: std::vector push_back failed");
        Children [0]->SetPosition (VEC2I (Rect.Left + 5, Rect.Top + 5));
    }

    ((LABEL *) Children [0])->AttachFont (aFont);
}

//==============================================================================
// Sets button label value
//==============================================================================
void G3::GUI::BUTTON::SetCaption (const string &aCaption) {
    if (Children.empty () || !Children [0]) {
        Children.push_back (new LABEL);

        Assert (Children [0], "BUTTON::SetCaption: std::vector push_back failed");
        Children [0]->Rect = RECTI (Rect.Left + 5, Rect.Top + 5, Rect.Right - 5, Rect.Bottom - 5);
        ((LABEL *) Children [0])->ClippedByRect = true;
    }

    ((LABEL *) Children [0])->SetValue (aCaption);

    Rect.Right = G3_MAX (Rect.Right, Children [0]->Rect.Right + 5);
    Rect.Bottom = G3_MAX (Rect.Bottom, Children [0]->Rect.Bottom + 5);
}

//==============================================================================
// Draws the button
//==============================================================================
void G3::GUI::BUTTON::Draw (float aElapsedTime) {
    if (!Visible)
        return;

    Assert (State <= 2, "BUTTON::Draw: State member is invalid (< 0 || > 2)");

    glPushMatrix ();
    glDisable (GL_TEXTURE_2D);

    // Button frame
    if (FgVisible) {
        // Button Foreground color
        glColor4f (FgColor [State].r, FgColor [State].g, FgColor [State].b, FgColor [State].a);

        glBegin (GL_LINE_STRIP);
        glVertex2i (Rect.Left, -Rect.Top);
        glVertex2i (Rect.Left, -Rect.Bottom);
        glVertex2i (Rect.Right, -Rect.Bottom);
        glVertex2i (Rect.Right, -Rect.Top);
        glVertex2i (Rect.Left, -Rect.Top);
        glEnd ();
    }
    // Button background
    if (BgVisible) {
        // Button Background color
        glColor4f (BgColor [State].r, BgColor [State].g, BgColor [State].b, BgColor [State].a);

        glBegin (GL_TRIANGLE_STRIP);
        glVertex2i (Rect.Left + 2, -Rect.Top - 2);
        glVertex2i (Rect.Left + 2, -Rect.Bottom + 2);
        glVertex2i (Rect.Right - 2, -Rect.Top - 2);
        glVertex2i (Rect.Right - 2, -Rect.Bottom + 2);
        glEnd ();
    }

    glEnable (GL_TEXTURE_2D);

    if (!Children.empty () && Children [0]) {
        Assert (((LABEL *) Children [0])->Font, "BUTTON::Draw: Child's Font member is a NULL pointer");

        Children [0]->Draw (aElapsedTime);
    }

    glPopMatrix ();
}
